VPC 内の Lambda から別の Lambda を呼び出す際にタイムアウトが発生したときの対処方法

VPC 内の Lambda から別の Lambda を呼び出す際にタイムアウトが発生したときの対処方法

AWS SDK で Lambda を呼び出す際は、Lambda のサービスエンドポイントとの疎通性が必要です。
Clock Icon2023.12.03

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

この記事は アノテーション株式会社 AWS Technical Support Advent Calendar 2023 | Advent Calendar 2023 - Qiita 3日目の記事です。

困っていた内容

プライベートサブネットに設定した VPC Lambda から別の VPC Lambda を AWS SDK(Boto3)の invoke メソッドで呼び出す際、タイムアウトで失敗します。
対処方法を教えてください。

どう対応すればいいの?

AWS SDK で Lambda を呼び出す際、Lambda のサービスエンドポイントに接続する必要がありますので、その疎通性がない可能性があります。
NAT ゲートウェイや Lambda の VPC エンドポイントを作成し、Lambda のサービスエンドポイントとの疎通性を確保してください。

AWS Lambda エンドポイントとクォータ - AWS 全般のリファレンス

AWS のサービスにプログラムで接続するには、エンドポイントを使用します。

以下では実際にプライベートサブネットに設定した VPC Lambda から、別の VPC Lambda を呼び出してみます。
まずは Lambda のサービスエンドポイントとの疎通性がない状態でタイムアウトが発生することを確認し、その後に NAT Gateway や VPC エンドポイントを作成して Lambda を呼び出せることを確認します。

呼び出す側の VPC Lambda の設定

ソースコード(ランタイム Python3.11)

import json
import boto3

client = boto3.client('lambda')

FunctionName = '呼び出される Lambda 関数の名前'

def lambda_handler(event, context):
    
    payload = {
        'message': 'test'
    }
    
    res = client.invoke(
            FunctionName = FunctionName,
            Payload = json.dumps(payload)
        )
    # 呼び出される Lambda 関数のレスポンスの内容を出力し、呼び出しに成功したことを確認する
    print(json.loads(res['Payload'].read()))

VPC設定

Lambda 関数の VPC 設定は以下のとおりで、今回は 1 つだけプライベートサブネットを設定しています。

サブネットのルートテーブルは以下であり、プライベートサブネットとなります。

なお、ネットワーク ACL は全て許可しています。

セキュリティグループはインバウンドルールはなし、アウトバウンドルールは HTTPS(ポート 443)で 0.0.0.0/0 を許可しています。

IAMロール

管理ポリシーの AWSLambdaVPCAccessExecutionRole をアタッチし、インラインポリシーで lambda:InvokeFunction を許可しています。

呼び出される側の VPC Lambda の設定

ソースコード(ランタイム Python3.11)

import json

def lambda_handler(event, context):
    print(event)

    return 'success'

その他

その他の設定は、以下以外呼び出す側の Lambda と同一です。

  • IAM ロールに lambda:InvokeFunction の許可は付与していない
  • セキュリティグループはインバウンド・アウトバウンドルールともになし

なお、呼び出される VPC Lambda 側でセキュリティグループのインバウンドルールを開く必要はありません。

設定したセキュリティグループは VPC Lambda で利用される ENI にアタッチされるところ、Lambda 関数を呼び出す Invoke API は Lambda のサービスエンドポイントに対してリクエストを行い、 ENI に対してリクエストを行わないからです。

タイムアウトが発生することを確認する

上記の設定で呼び出す側の VPC Lambda をテスト実行したところ、Lambda のサービスエンドポイントとの疎通性がないので想定どおりタイムアウトとなりました。

Task timed out after 3.01 seconds

NAT ゲートウェイを利用して、Lambda を呼び出す

NAT ゲートウェイを作成し、以下のように Lambda 関数に設定したプライベートサブネットのルートテーブルのルートに追加します。
なお、NAT ゲートウェイを作成するサブネットには Lambda 関数に設定した VPC 内のパブリックサブネットを指定しています。

NAT ゲートウェイの設定ができましたので、タイムアウトとならずに成功するはずです。
呼び出す側の VPC Lambda をテスト実行したところ、タイムアウトにならず呼び出される VPC Lambda からのレスポンスを確認できました。

success

NAT ゲートウェイを利用した検証は完了したので、NAT ゲートウェイや追加したルートは削除しておきます。

VPCエンドポイントを利用して、Lambda を呼び出す

次に、VPC エンドポイントを利用して Lambda を呼び出してみます。
VPC エンドポイントの主要な設定は以下にして作成しています。

サービスカテゴリ:AWS のサービス
サービス:com.amazonaws.ap-northeast-1.lambda
VPC:Lambda に設定した VPC
DNS名を有効化:有効(デフォルト設定)
セキュリティグループ:インバウンドルールで HTTPS(ポート 443)で 10.0.0.0/16(VPCのCIDR)を許可したセキュリティグループを指定

なお、VPC では DNSホスト名、DNS解決の設定は有効化済みです。
VPC エンドポイントの作成が完了したら、呼び出す側の VPC Lambda をテスト実行してみます。
テスト実行したところ、以下のとおり、NAT ゲートウェイを利用した際と同様にタイムアウトにならずに呼び出される VPC Lambda からのレスポンスを確認できました。

success

VPC エンドポイントや NAT ゲートウェイを利用してもタイムアウトが発生する場合

次の設定により疎通性がないことが原因の可能性が考えられますので、意図した設定であるかご確認ください。

  • VPC Lambda や VPC エンドポイントのセキュリティグループの設定
  • サブネットのネットワーク ACL の設定
  • サブネットのルートテーブルの設定
  • VPC の DHCP オプションセットや DNS の設定(適切な名前解決ができていない可能性がある)

名前解決が怪しい場合、VPC Lambda と同一のサブネットに EC2 インスタンスを起動して、同インスタンスから適切な名前解決ができるか確認することも有用です。

参考資料

AWS Lambda エンドポイントとクォータ - AWS 全般のリファレンス

Invoke API

アウトバウンドネットワークを VPC 内のリソースに接続する - AWS Lambda

Lambda 用のインバウンドインターフェイス VPC エンドポイントの接続 - AWS Lambda

AWS Lambda の一貫したエラーと断続的な DNS 関連エラーをトラブルシューティングする方法を教えてください。 | AWS re:Post

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.